<template>
  <view class="custom-swiper">
    <!-- 轮播容器 -->
    <view class="swiper-container"
          @touchstart="handleTouchStart"
          @touchmove="handleTouchMove"
          @touchend="handleTouchEnd"
          :style="{
            transform: `translateX(${offsetX}px)`,
            transition: isDragging ? 'none' : `transform ${duration}ms ease-out`
          }">
      <!-- 轮播项 -->
      <view class="swiper-item"
            v-for="(item, index) in items"
            :key="index"
            :style="getItemStyle(index)"
            @click="handleItemClick(item)">
        <image class="item-image" :src="item.image" mode="aspectFill" />
        <view class="item-content">
          <text class="item-title">{{ item.title }}</text>
          <text class="item-desc">{{ item.desc }}</text>
        </view>
      </view>
    </view>

    <!-- 指示器 -->
    <view class="indicator-container">
      <view v-for="(item, index) in items"
            :key="index"
            class="indicator-dot"
            :class="{ active: currentIndex === index }"></view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted,defineProps } from 'vue'

const props = defineProps({
  items: {
    type: Array,
    default: () => []
  },
  duration: {
    type: Number,
    default: 300
  }
})

const currentIndex = ref(0)
const offsetX = ref(0)
const startX = ref(0)
const moveX = ref(0)
const containerWidth = ref(300)
const isDragging = ref(false)
const isAnimating = ref(false)

// 获取卡片样式
const getItemStyle = (index) => {
  const position = (index - currentIndex.value) * containerWidth.value + offsetX.value
  const scale = Math.max(0.9, 1 - Math.abs(position) / (containerWidth.value * 2))
  const zIndex = props.items.length - Math.abs(index - currentIndex.value)
  const opacity = Math.max(0.7, 1 - Math.abs(position) / (containerWidth.value * 2))

  return {
    transform: `scale(${scale})`,
    zIndex: zIndex,
    opacity: opacity,
    pointerEvents: isAnimating.value ? 'none' : 'auto'
  }
}

// 触摸开始
const handleTouchStart = (e) => {
  if (isAnimating.value) return
  isDragging.value = true
  startX.value = e.touches[0].clientX
  moveX.value = startX.value
}

// 触摸移动
const handleTouchMove = (e) => {
  if (!isDragging.value || isAnimating.value) return

  moveX.value = e.touches[0].clientX
  const deltaX = moveX.value - startX.value

  // 限制第一张和最后一张的拖动范围
  let maxOffset = containerWidth.value * 0.5
  if (currentIndex.value === 0 && deltaX > 0) {
    maxOffset = Math.min(maxOffset, deltaX * 0.3) // 第一张向右拖动阻力
  } else if (currentIndex.value === props.items.length - 1 && deltaX < 0) {
    maxOffset = Math.min(maxOffset, Math.abs(deltaX) * 0.3) // 最后一张向左拖动阻力
  }

  offsetX.value = Math.max(-maxOffset, Math.min(maxOffset, deltaX))
}

// 触摸结束
const handleTouchEnd = () => {
  if (!isDragging.value || isAnimating.value) return

  isDragging.value = false
  const distance = moveX.value - startX.value
  const threshold = containerWidth.value / 4

  isAnimating.value = true

  // 判断滑动方向
  if (Math.abs(distance) > threshold) {
    if (distance > 0 && currentIndex.value > 0) {
      // 向左滑动，上一张
      currentIndex.value--
    } else if (distance < 0 && currentIndex.value < props.items.length - 1) {
      // 向右滑动，下一张
      currentIndex.value++
    }
  }

  // 平滑回到正确位置
  resetPosition()
}

// 重置位置
const resetPosition = () => {
  const targetOffset = -currentIndex.value * containerWidth.value
  offsetX.value = targetOffset

  // 动画结束后重置状态
  setTimeout(() => {
    isAnimating.value = false
  }, props.duration)
}

// 点击卡片
const handleItemClick = (item) => {
  if (isDragging.value || isAnimating.value) return
  console.log('点击了卡片:', item)
}

// 初始化容器宽度
onMounted(() => {
  uni.getSystemInfo({
    success: (res) => {
      containerWidth.value = res.windowWidth * 0.85
      offsetX.value = -currentIndex.value * containerWidth.value
    }
  })
})
</script>

<style lang="scss" scoped>
/* 样式保持不变 */
.custom-swiper {
  width: 100%;
  height: 350rpx;
  position: relative;
  overflow: hidden;
}

.swiper-container {
  display: flex;
  height: 100%;
  will-change: transform;
}

.swiper-item {
  width: 85vw;
  height: 100%;
  flex-shrink: 0;
  border-radius: 16rpx;
  overflow: hidden;
  position: relative;
  transition: all 0.3s ease;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  backface-visibility: hidden;
}

.item-image {
  width: 100%;
  height: 100%;
}

.item-content {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 24rpx;
  background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
  color: #fff;

  .item-title {
    font-size: 32rpx;
    font-weight: bold;
    display: block;
  }

  .item-desc {
    font-size: 24rpx;
    display: block;
    margin-top: 8rpx;
  }
}

.indicator-container {
  display: flex;
  justify-content: center;
  margin-top: 20rpx;

  .indicator-dot {
    width: 12rpx;
    height: 12rpx;
    border-radius: 50%;
    background-color: #ccc;
    margin: 0 8rpx;
    transition: all 0.3s;

    &.active {
      width: 30rpx;
      border-radius: 6rpx;
      background-color: #007aff;
    }
  }
}
</style>